home *** CD-ROM | disk | FTP | other *** search
/ Complete Linux / Complete Linux.iso / docs / apps / database / ingres04.lzh / source / dbu / create.c < prev    next >
Encoding:
C/C++ Source or Header  |  1986-05-01  |  12.6 KB  |  570 lines

  1. # include    <pv.h>
  2. # include    <ingres.h>
  3. # include    <access.h>
  4. # include    <aux.h>
  5. # include    <catalog.h>
  6. # include    <symbol.h>
  7. # include    <lock.h>
  8. # include    <func.h>
  9. # include    <sccs.h>
  10. # include    <errors.h>
  11.  
  12. SCCSID(@(#)create.c    8.7    5/1/86)
  13.  
  14. extern    short    tTdbu[];
  15. extern    int    create();
  16. extern    int    null_fn();
  17.  
  18. struct fn_def CreateFn =
  19. {
  20.     "CREATE",
  21.     create,
  22.     null_fn,
  23.     null_fn,
  24.     NULL,
  25.     0,
  26.     tTdbu,
  27.     100,
  28.     'Z',
  29.     0
  30. };
  31.  
  32. /*
  33. **  CREATE -- create new relation
  34. **
  35. **    This module creates a brand new relation in the current
  36. **    directory (database).  The relation is always created as
  37. **    a paged heap.  It may not redefine an existing relation,
  38. **    or rename a system catalog.
  39. **
  40. **    Trace Flags:
  41. **        31
  42. */
  43.  
  44.  
  45. struct domain
  46. {
  47.     char    *name;
  48.     char    frmt;
  49.     char    frml;
  50. };
  51.  
  52. /*
  53. **  CREATE -- create new relation
  54. **
  55. **    This routine is the driver for the create module.
  56. **
  57. **    Parameters:
  58. **        pc -- parameter count
  59. **        pv -- parameter vector:
  60. **            0 -- relation status (relstat) -- stored into
  61. **                the 'relstat' field in the relation
  62. **                relation, and used to determine the
  63. **                caller.  Interesting bits are:
  64. **
  65. **                S_INDEX -- means called by the index
  66. **                    processor.  If set, the 'relindxd'
  67. **                    field will also be set to -1
  68. **                    (SECINDEX) to indicate that this
  69. **                    relation is a secondary index.
  70. **                S_CATALOG -- this is a system catalog.
  71. **                    If set, this create was called
  72. **                    from creatdb, and the physical
  73. **                    file is not created.  Also, the
  74. **                    expiration date is set infinite.
  75. **                S_VIEW -- this is a view.  Create has
  76. **                    been called by the 'define'
  77. **                    statement, rather than the
  78. **                    'create' statement.  The physical
  79. **                    file is not created.
  80. **
  81. **            1 -- relation name.
  82. **            2 -- attname1
  83. **            3 -- format1
  84. **            4, etc -- attname, format pairs.
  85. **
  86. **    Returns:
  87. **        zero -- successful create.
  88. **        else -- failure somewhere.
  89. **
  90. **    Side Effects:
  91. **        A relation is created (this is a side effect?).  This
  92. **        means entries in the 'relation' and 'attribute' cata-
  93. **        logs, and (probably) a physical file somewhere, with
  94. **        one page already in it.
  95. **
  96. **    Trace Flags:
  97. **        31
  98. */
  99.  
  100. create(pc, pv)
  101. int    pc;
  102. PARM    pv[];
  103. {
  104.     register PARM        *pp;
  105.     register int        i;
  106.     int            bad;
  107.     struct domain        domain[MAXDOM];
  108.     struct domain        *dom;
  109.     char            *relname, tempname[MAXNAME+3];
  110.     struct tup_id        tid;
  111.     struct relation        rel, key;
  112.     struct attribute    att;
  113.     DESC            desr;
  114.     extern char        *Usercode;
  115.     extern DESC        Reldes, Attdes;
  116.     extern int        errno;
  117.     register int        relstat;
  118.     long            temptid;
  119.     long            npages;
  120.     int            fdes;
  121.     bool            internal;
  122.  
  123. #    ifdef xZTR1
  124.     if (tTf(31, -1))
  125.     {
  126.         printf("creating %s\n", pv[1].pv_val.pv_str);
  127.     }
  128. #    endif
  129.     pp = pv;
  130.     relstat = oatoi(pp[0].pv_val.pv_str);
  131.     /*
  132.     **    If this database has query modification, then default
  133.     **    to denial on all user relations.
  134.     **    (Since views cannot be protected, this doesn't apply to them)
  135.     */
  136.     if ((Admin.adhdr.adflags & A_QRYMOD) && ((relstat & (S_VIEW || S_CATALOG)) == 0))
  137.         relstat |= (S_PROTALL | S_PROTRET);
  138.     relname = (++pp)->pv_val.pv_str;
  139.     internal = bequal(relname, "_SYS", 4);
  140.     ingresname(relname, Usercode, rel.relid);
  141.     bmove(rel.relid, att.attrelid, MAXNAME + 2);
  142.     opencatalog("relation", OR_WRITE);
  143.  
  144.     /* check for duplicate relation name */
  145.     if ((relstat & S_CATALOG) == 0)
  146.     {
  147.         if (openr(&desr, OR_RELTID, relname) == 0)
  148.         {
  149.             if (bequal(desr.reldum.relowner, rel.relowner, 2))
  150.             {
  151.                 return (error(DUPRELNAME, relname, 0));    /* bad relname */
  152.             }
  153.             if (desr.reldum.relstat & S_CATALOG)
  154.             {
  155.                 return (error(SYSRELNAME, relname, 0));    /* attempt to rename system catalog */
  156.             }
  157.         }
  158.     }
  159.     opencatalog("attribute", OR_WRITE);
  160.  
  161.     /* initialize structures for system catalogs */
  162.     initstructs(&att, &rel);
  163.     rel.relstat = relstat;
  164.     if ((relstat & S_CATALOG) != 0)
  165.         rel.relsave = 0;
  166.     else if ((relstat & S_INDEX) != 0)
  167.         rel.relindxd = SECINDEX;
  168.     
  169. #    ifdef xZTR3
  170.     if (tTf(31, 2))
  171.     {
  172.         printf("\nrel->relprim = %D\n", rel.relprim);
  173.         printup(&Reldes, &rel);
  174.     }
  175. #    endif
  176.  
  177.     /* check attributes */
  178.     pp++;
  179.     for (i = pc - 2; i > 0; i -= 2)
  180.     {
  181.         bad = chk_att(&rel, pp[0].pv_val.pv_str, pp[1].pv_val.pv_str, domain, internal);
  182.         if (bad != 0)
  183.         {
  184.             return (error(bad, relname, pp[0].pv_val.pv_str, pp[1].pv_val.pv_str, 0));
  185.         }
  186.         pp += 2;
  187.     }
  188.  
  189.     /*
  190.     ** Create files if appropriate. Concurrency control for
  191.     ** the create depends on the actual file. To prevent
  192.     ** to users with the same usercode from creating the
  193.     ** same relation at the same time, their is check
  194.     ** on the existence of the file. The important events are
  195.     ** (1) if a tuple exists in the relation relation then
  196.     ** the relation really exists. (2) if the file exists then
  197.     ** the relation is being created but will not exist for
  198.     ** use until the relation relation tuple is present.
  199.     ** For VIEWS, the file is used for concurrency control
  200.     ** during the create but is removed afterwards.
  201.     */
  202.     if ((relstat & S_CATALOG) == 0)
  203.     {
  204.         /* for non system named temporary relations
  205.         ** set a critical section lock while checking the
  206.         ** existence of a file.  If it exists, error return(DUPRELNAME)
  207.         ** else create file.
  208.         */
  209.         temptid = 0;
  210.         if (Lockrel && (!bequal(rel.relid,"_SYS",4)))
  211.         {
  212.             temptid = -1;
  213.             setcsl(temptid);    /* set critical section lock */
  214.             if ((fdes = open(rel.relid,O_RDONLY)) >= 0)
  215.             {
  216.                         /* file already exists */
  217.                 close(fdes);
  218.                 unlcs(temptid);    /* release critical section lock */
  219.                 return (error(DUPRELNAME, relname, 0));
  220.             }
  221.             errno = 0;    /* file doesn't exist */
  222.         }
  223.         ingresname(rel.relid, rel.relowner, tempname);
  224.         desr.relfp = creat(tempname, FILEMODE);
  225.         if (temptid != 0)
  226.             unlcs(temptid);    /* release critical section lock */
  227.         if (desr.relfp < 0)
  228.             syserr("create: creat %s", rel.relid);
  229.         desr.reltid.ltid = -1L;    /* init reltid to unused */
  230.         if ((relstat & S_VIEW) == 0)
  231.         {
  232.             npages = 1;
  233.             if (i = formatpg(&desr, npages))
  234.                 syserr("create: formatpg %d", i);
  235.         }
  236.  
  237.         close(desr.relfp);
  238.     }
  239.  
  240.     /* insert attributes into attribute relation */
  241.     pp = pv + 2;
  242.     dom = domain;
  243.     for (i = pc - 2; i > 0; i -= 2)
  244.     {
  245.         ins_att(&Attdes, &att, dom++);
  246.         pp += 2;
  247.     }
  248.  
  249.     /*
  250.     ** Flush the attributes. This is necessary for recovery reasons.
  251.     ** If for some reason the relation relation is flushed and the
  252.     ** machine crashes before the attributes are flushed, then recovery
  253.     ** will not detect the error.
  254.     ** The call below cannot be a "noclose" without major changes to
  255.     ** creatdb.
  256.     */
  257.     if (i = pageflush(0))
  258.         syserr("create:flush att %d", i);
  259.  
  260.     if (i = insert(&Reldes, &tid, &rel, FALSE))
  261.         syserr("create: insert(rel, %.14s) %d", rel.relid, i);
  262.  
  263.     if (relstat & S_VIEW)
  264.         unlink(tempname);
  265.     return (0);
  266. }
  267.  
  268.  
  269.  
  270. /*
  271. **  CHK_ATT -- check attribute for validity
  272. **
  273. **    The attribute is checked to see if
  274. **    * it's name is ok (within MAXNAME bytes)
  275. **    * it is not a duplicate name
  276. **    * the format specified is legal
  277. **    * there are not a ridiculous number of attributes
  278. **      (ridiculous being defined as anything over MAXDOM - 1)
  279. **    * the tuple is not too wide to fit on one page
  280. **
  281. **    Parameters:
  282. **        rel -- relation relation tuple for this relation.
  283. **        attname -- tentative name of attribute.
  284. **        format -- tentative format for attribute.
  285. **        domain -- a 'struct domain' used to determine dupli-
  286. **            cation, and to store the resulting name and
  287. **            format in.
  288. **
  289. **    Returns:
  290. **        zero -- OK
  291. **        5104 -- bad attribute name.
  292. **        5105 -- duplicate attribute name.
  293. **        5106 -- bad attribute format.
  294. **        5107 -- too many attributes.
  295. **        5108 -- tuple too wide.
  296. **
  297. **    Side Effects:
  298. **        'rel' has the relatts and relwid fields updated to
  299. **        reflect the new attribute.
  300. **
  301. **    Trace Flags:
  302. **        31
  303. */
  304.  
  305. chk_att(rel, attname, format, domain, internal)
  306. struct relation    *rel;
  307. char        *attname, *format;
  308. struct domain    domain[];
  309. bool        internal;
  310. {
  311.     register int            i;
  312.     register struct relation    *r;
  313.  
  314.     r = rel;
  315.  
  316. #    ifdef xZTR3
  317.     if (tTf(31, 1))
  318.         printf("chk_att %s %s\n", attname, format);
  319. #    endif
  320.  
  321.     if (sequal(attname, "tid"))
  322.         return (BADATTRNAME);        /* bad attribute name */
  323.     if ((i = dup_att(attname, r->relatts, domain)) < 0)
  324.         return (DUPATTRNAME);        /* duplicate attribute */
  325.     if (formck(format, &domain[i], internal))
  326.         return (BADATTRFORMAT);        /* bad attribute format */
  327.     r->relatts++;
  328. #ifndef    VAX
  329. /* round the location up so that we don't get off address traps */
  330.     if (domain[i].frmt != CHAR)
  331.         r->relwid=((r->relwid-1)|((domain[i].frml&I1MASK)-1))+1;
  332. #endif
  333.     r->relwid += domain[i].frml & I1MASK;
  334.     if (r->relatts >= MAXDOM)
  335.         return (TOOMANYDOMS);        /* too many attributes */
  336.     if (r->relwid > MAXTUP && (r->relstat & S_VIEW) == 0)
  337.         return (RELTOOWIDE);        /* tuple too wide */
  338.     return (0);
  339. }
  340.  
  341.  
  342.  
  343.  
  344. /*
  345. **  INS_ATT -- insert attribute into attribute relation
  346. **
  347. **    Parameters:
  348. **        des -- relation descriptor for the attribute catalog.
  349. **        att -- attribute tuple, preinitialized with all sorts
  350. **            of good stuff (everything except 'attname',
  351. **            'attfrmt', and 'attfrml'; 'attid' and 'attoff'
  352. **            must be initialized to zero before this routine
  353. **            is called the first time.
  354. **        dom -- 'struct domain' -- the information needed about
  355. **            each domain.
  356. **
  357. **    Returns:
  358. **        none
  359. **
  360. **    Side Effects:
  361. **        The 'att' tuple is updated in the obvious ways.
  362. **        A tuple is added to the 'attribute' catalog.
  363. **
  364. **    Trace Flags:
  365. **        none currently
  366. */
  367.  
  368. ins_att(des, att, dom)
  369. DESC            *des;
  370. struct attribute    *att;
  371. struct domain        *dom;
  372. {
  373.     register int        i;
  374.     struct tup_id        tid;
  375.     register struct domain    *d;
  376.  
  377.     d = dom;
  378.  
  379.     pmove(d->name, att->attname, MAXNAME, ' ');
  380. #ifndef    VAX
  381. /* round the location up so that we don't get off address traps */
  382.     if (d->frmt != CHAR)
  383.         att->attoff=((att->attoff-1)|(d->frml-1))+1;
  384. #endif
  385.     att->attfrmt = d->frmt;
  386.     att->attfrml = d->frml;
  387.     att->attid++;
  388.     if (insert(des, &tid, att, FALSE))
  389.         syserr("ins_att: insert(att, %s)", d->name);
  390.     att->attoff += att->attfrml & I1MASK;
  391. }
  392.  
  393.  
  394.  
  395.  
  396. /*
  397. **  DUP_ATT -- check for duplicate attribute
  398. **
  399. **    The attribute named 'name' is inserted into the 'attalias'
  400. **    vector at position 'count'.  'Count' should be the count
  401. **    of existing entries in 'attalias'.  'Attalias' is checked
  402. **    to see that 'name' is not already present.
  403. **
  404. **    Parameters:
  405. **        name -- the name of the attribute.
  406. **        count -- the count of attributes so far.
  407. **        domain -- 'struct domain' -- the list of domains
  408. **            so far, names and types.
  409. **
  410. **    Returns:
  411. **        -1 -- attribute name is a duplicate.
  412. **        else -- index in 'domain' for this attribute (also
  413. **            the attid).
  414. **
  415. **    Side Effects:
  416. **        The 'domain' vector is extended.
  417. **
  418. **    Trace Flags:
  419. **        none
  420. */
  421.  
  422. dup_att(name, count, domain)
  423. char        *name;
  424. int        count;
  425. struct domain    domain[];
  426. {
  427.     register struct domain    *d;
  428.     register int        lim;
  429.     register int        i;
  430.  
  431.     lim = count;
  432.     d = domain;
  433.  
  434.     for (i = 0; i < lim; i++)
  435.         if (sequal(name, d++->name))
  436.             return (-1);
  437.     if (count < MAXDOM)
  438.         d->name = name;
  439.     return (i);
  440. }
  441.  
  442.  
  443.  
  444.  
  445. /*
  446. **  INITSTRUCTS -- initialize relation and attribute tuples
  447. **
  448. **    Structures containing images of 'relation' relation and
  449. **    'attribute' relation tuples are initialized with all the
  450. **    information initially needed to do the create.  Frankly,
  451. **    the only interesting part is the the expiration date
  452. **    computation; longconst(9, 14976) is exactly the number
  453. **    of seconds in one week.
  454. **
  455. **    Parameters:
  456. **        att -- attribute relation tuple.
  457. **        rel -- relation relation tuple.
  458. **
  459. **    Returns:
  460. **        none
  461. **
  462. **    Side Effects:
  463. **        'att' and 'rel' are initialized.
  464. **
  465. **    Requires:
  466. **        time -- to get the current date.
  467. **
  468. **    Called By:
  469. **        create
  470. **
  471. **    Trace Flags:
  472. **        none
  473. **
  474. **    Diagnostics:
  475. **        none
  476. **
  477. **    Syserrs:
  478. **        none
  479. **
  480. **    History:
  481. **        2/27/78 (eric) -- documented.
  482. */
  483.  
  484. initstructs(att, rel)
  485. register struct attribute    *att;
  486. register struct relation    *rel;
  487. {
  488.     /* setup expiration date (today + one week) */
  489.     time(&rel->relstamp);
  490.     rel->relsave = rel->relstamp + 604800L;
  491.     rel->relfree = 0;
  492.     rel->reltups = 0;
  493.     rel->relatts = 0;
  494.     rel->relwid = 0;
  495.     rel->relprim = 1;
  496.     rel->relspec = M_HEAP;
  497.     rel->relindxd = 0;
  498.     rel->reldim = 0;
  499.     att->attxtra = 0;
  500.     att->attid = 0;
  501.     att->attoff = 0;
  502. }
  503.  
  504.  
  505.  
  506. /*
  507. **  CHECK ATTRIBUTE FORMAT AND CONVERT
  508. **
  509. **    The string 'a' is checked for a valid attribute format
  510. **    and is converted to internal form.
  511. **
  512. **    zero is returned if the format is good; one is returned
  513. **    if it is bad.  If it is bad, the conversion into a is not
  514. **    made.
  515. **
  516. **    A format of CHAR can be length zero only if this
  517. **    create was generated internally.
  518. */
  519.  
  520. formck(a, dom, internal)
  521. char        *a;
  522. struct domain    *dom;
  523. bool        internal;
  524. {
  525.     int            len;
  526.     register int        i;
  527.     char            c;
  528.     register char        *p;
  529.     register struct domain    *d;
  530.  
  531.     p = a;
  532.     c = *p++;
  533.     d = dom;
  534.  
  535.     len = atoi(p);
  536.     i = len;
  537.  
  538.     switch (c)
  539.     {
  540.  
  541.       case INT:
  542.         if (i == 1 || i == 2 || i == 4)
  543.         {
  544.             d->frmt = INT;
  545.             d->frml = i;
  546.             return (0);
  547.         }
  548.         return (1);
  549.  
  550.       case FLOAT:
  551.         if (i == 4 || i == 8)
  552.         {
  553.             d->frmt = FLOAT;
  554.             d->frml = i;
  555.             return (0);
  556.         }
  557.         return (1);
  558.  
  559.       /* note: should disallow c0 from user (but needed internally) */
  560.       case CHAR:
  561.         if (i > MAXFIELD || i < 0 || (i == 0 && !internal))
  562.             return (1);
  563.         d->frmt = CHAR;
  564.         d->frml = i;
  565.         return (0);
  566.     }
  567.     return (1);
  568.  
  569. }
  570.